home *** CD-ROM | disk | FTP | other *** search
- /*----------------------------------------------------------------------
- * $Id: Lastrev.c++,v 1.7 1993/11/30 15:16:29 carlson Exp $
- *
- * This program collects information about the revisions and symbols
- * defined in RCS files and then prints this information.
- *
- * Revision History:
- * $Log: Lastrev.c++,v $
- // Revision 1.7 1993/11/30 15:16:29 carlson
- // Modified so that it will compile on 4.0.5 (added include file for getopt.h).
- // Fixed a bug where it won't see the end of a comment line if comment
- // contains a semicolon.
- // Use the macro S_ISDIR instead of testing the flag.
- // If the file being tested is a directory, skip it.
- //
- // Revision 1.3.1.1 93/11/29 18:37:44 carlson
- // test file
- //
- // Revision 1.6 93/11/19 00:13:27 carlson
- // Needed to intialize all the elements of every class to something.
- // Changed all '\n' in print statements to use endl.
- // Fixed a couple of places where I didn't reset a pointer to the very
- // beginning (since it was automatically incremented in a loop).
- // Changed the way branches were scanned and added. The old way didn't
- // allow for multiple branches to be specified in one 'branch' statement
- // but the new way does.
- // Found a place where an error message didn't end with endl;
- //
- // Revision 1.5 1993/11/18 21:34:54 carlson
- // Fixed a bug where it never inserted symbols or deltas after the first.
- // Moved the printing of the titles to a different place.
- //
- // Revision 1.4 1993/06/22 00:03:36 chris
- // Completed this program. Only thing left to do is allow user to specify
- // a directory and not each file.
- //
- // Revision 1.3 1993/06/14 05:44:03 chris
- // Put most of work into subroutine.
- //
- // Revision 1.2 1993/06/14 04:33:27 chris
- // Made numberous improvements. Still not finished.
- //
- *
- * Wed May 26 15:29:42 1993
- * Rewritten from scratch because I can't find the original sources.
- *----------------------------------------------------------------------*/
-
- #include <stdio.h>
- #include <errno.h>
- #include <ctype.h>
- #include <string.h>
- #include <iostream.h>
- #include <fstream.h>
- #include <stdlib.h>
- #include <memory.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #ifdef __SVR3
- #include <getopt.h>
- #endif
-
- // #define DEBUG
- // #define DEBUG1
-
- #define ARRAY_SIZE 10
- #define MAX_BRANCHES 10
-
- #define SKIP_SPACE(c) while (*c && isspace (*c)) c++
- #define TAB_OUT(c,to) (c) = (c) - ((c) % 8); \
- while ((c) < (to)) { cout << '\t'; c += 8; }
-
- #define False 0
- #define True 1
-
- /*========================================================================
- * Revision class
- *========================================================================*/
-
- typedef enum {SAME = 0, HIGHER, LOWER, MORE_LEVELS, LESS_LEVELS,
- DIFFERENT, DIFFERENT_BRANCH, ERROR} dType;
-
- class Revision
- {
- private:
- short number[ARRAY_SIZE];
- char *author;
- char *state;
- Revision *branches[MAX_BRANCHES];
- Revision *nextRev;
-
- void convertToArray (char *rev, short *array);
- char *convertToString (short *array);
-
- public:
- Revision (char *c = NULL);
- Revision (Revision &r);
- ~Revision ();
- Revision& operator= (char *r);
- Revision& operator= (Revision &r);
-
- void SetRevision (char *r);
- void SetAuthor (char *s);
- void SetState (char *s);
- void AddBranch (Revision *r);
- void SetNext (Revision *r);
-
- dType CompareRevs (Revision &r);
- Revision *ConditionalSetRevision (Revision *rev, Revision *base);
-
- char *GetRevision (void);
- char *GetState (void) { return state; }
- Revision *GetNext (void) { return nextRev; }
- void printRev (char *indent);
- virtual void printAll (char *indent);
- };
-
- /*------------------------------------------------------------------------
- * Revision::Revision
- *------------------------------------------------------------------------*/
-
- Revision::Revision (char *c)
- {
- number[0] = -1;
- if (c)
- convertToArray (c, number);
- author = NULL;
- state = NULL;
- branches[0] = NULL;
- nextRev = NULL;
- }
-
- /*------------------------------------------------------------------------
- * Revision::Revision
- *------------------------------------------------------------------------*/
-
- Revision::Revision (Revision &r)
- {
- memcpy (number, r.number, sizeof (number));
- state = new char [strlen (r.state) + 1];
- strcpy (state, r.state);
- author = new char [strlen (r.author) + 1];
- strcpy (author, r.author);
- memcpy (branches, r.branches, sizeof (branches));
- nextRev = r.nextRev;
- }
-
- /*------------------------------------------------------------------------
- * Revision::~Revision
- *------------------------------------------------------------------------*/
-
- Revision::~Revision ()
- {
- delete [] state;
- }
-
- /*------------------------------------------------------------------------
- * Revision::operator=
- *------------------------------------------------------------------------*/
-
- Revision& Revision::operator= (char *r)
- {
- convertToArray (r, number);
- if (state)
- delete [] state;
- state = NULL;
- branches[0] = NULL;
- nextRev = NULL;
-
- return *this;
- }
-
- /*------------------------------------------------------------------------
- * Revision::operator=
- *------------------------------------------------------------------------*/
-
- Revision& Revision::operator= (Revision &r)
- {
- memcpy (number, r.number, sizeof (number));
- if (state)
- delete [] state;
- state = new char [sizeof (r.state) + 1];
- strcpy (state, r.state);
- memcpy (branches, r.branches, sizeof (branches));
- nextRev = r.nextRev;
-
- return *this;
- }
-
- /*------------------------------------------------------------------------
- * Revision::SetRevision
- *------------------------------------------------------------------------*/
-
- void Revision::SetRevision (char *r)
- {
- convertToArray (r, number);
- }
-
- /*------------------------------------------------------------------------
- * Revision::SetAuthor
- *------------------------------------------------------------------------*/
-
- void Revision::SetAuthor (char *s)
- {
- if (author)
- delete [] author;
- author = new char [strlen (s) + 1];
- strcpy (author, s);
- }
-
- /*------------------------------------------------------------------------
- * Revision::SetState
- *------------------------------------------------------------------------*/
-
- void Revision::SetState (char *s)
- {
- if (state)
- delete [] state;
- state = new char [strlen (s) + 1];
- strcpy (state, s);
- }
-
- /*------------------------------------------------------------------------
- * Revision::AddBranch
- *------------------------------------------------------------------------*/
-
- void Revision::AddBranch (Revision *r)
- {
- int i;
- for (i = 0; i < MAX_BRANCHES; i++)
- {
- if (branches[i] == NULL)
- {
- branches[i] = r;
- if (i < (MAX_BRANCHES - 1))
- branches[i+1] = NULL;
- break;
- }
- }
- }
-
- /*------------------------------------------------------------------------
- * Revision::SetNext
- *------------------------------------------------------------------------*/
-
- void Revision::SetNext (Revision *r)
- {
- nextRev = r;
- }
-
- /*------------------------------------------------------------------------
- * Revision::GetRevision
- *------------------------------------------------------------------------*/
-
- char *Revision::GetRevision (void)
- {
- return convertToString (number);
- }
-
- /*------------------------------------------------------------------------
- * Revision::convertToArray
- *------------------------------------------------------------------------*/
-
- void Revision::convertToArray (char *rev, short *array)
- {
- int i;
- char *tmp, *ptr, *pptr;
-
- tmp = new char [strlen (rev) + 1];
- strcpy (tmp, rev);
-
- for (pptr = ptr = tmp, i = 0; *pptr; )
- {
- while (isdigit (*ptr))
- ptr++;
- if (*ptr == '.')
- {
- *ptr = '\0';
- array[i++] = atoi (pptr);
- pptr = ++ptr;
- }
- else if (*ptr == '\0')
- {
- array[i++] = atoi (pptr);
- pptr = ptr;
- }
- else
- {
- cerr << "Revision::convertToArray: Illegal revision number - "
- << rev << endl;
- }
- }
-
- array[i] = -1;
- delete [] tmp;
- }
-
- /*------------------------------------------------------------------------
- * Revision::convertToString
- *------------------------------------------------------------------------*/
-
- char *Revision::convertToString (short *array)
- {
- static char retval[50], *rv;
- int i;
-
- for (i = 0, rv = retval; i < ARRAY_SIZE; i++)
- {
- if (array[i] == -1)
- break;
-
- if (rv != retval)
- *rv++ = '.';
- sprintf (rv, "%d", array[i]);
- rv = rv + strlen (rv);
- }
-
- return retval;
- }
-
- /*------------------------------------------------------------------------
- * Revision::CompareRevs
- *
- * This routine compares the revision numbers of two Revisions. It
- * assumes that \'this\' is set to the base revision and the passed
- * in revision is to find out if this revision should replace it.
- *------------------------------------------------------------------------*/
-
- dType Revision::CompareRevs (Revision &r)
- {
- int i;
- dType retval = ERROR;
-
- for (i = 0; i < ARRAY_SIZE; i++)
- {
- if (number[i] == -1)
- {
- if (r.number[i] == -1)
- retval = SAME; // The two revisions are the same
- else if ((i % 2) != 0)
- retval = MORE_LEVELS; // r has more levels but same base
- else
- retval = DIFFERENT_BRANCH; // r is a different branch
- break;
- }
- else if (r.number[i] == -1)
- {
- retval = LESS_LEVELS; // r has less levels
- break;
- }
- else if (number[i] < r.number[i])
- {
- retval = HIGHER; // r is a higher level
- break;
- }
- else if (number[i] > r.number[i])
- {
- retval = LOWER; // r is a lower level
- break;
- }
- }
-
- return retval;
- }
-
- /*------------------------------------------------------------------------
- * Revision::ConditionalSetRevision
- *
- * Used to set the actual revision when comparing to a base revision.
- * Usage:
- * actual = actual->ConditionalSetRevision (toTest, base);
- *------------------------------------------------------------------------*/
-
- Revision *Revision::ConditionalSetRevision (Revision *rev, Revision *base)
- {
- int i, retval = 0;
-
- for (i = 0; i < ARRAY_SIZE; i++)
- {
- if (rev->number[i] != base->number[i])
- {
- if ((base->number[i] == -1) && (rev->number[i+1] == -1))
- {
- if ((number[0] == -1) || (number[i] < rev->number[i]))
- retval = 1;
- }
- break;
- }
- }
-
- if (!retval && (rev->number[i] == -1) && (base->number[i] == -1))
- retval = 1;
-
- return retval ? rev : this;
- }
-
- /*------------------------------------------------------------------------
- * Revision::printRev
- *------------------------------------------------------------------------*/
-
- void Revision::printRev (char *indent)
- {
- int i;
-
- cout << indent;
- for (i = 0; (i < ARRAY_SIZE) && (number[i] != -1); i++)
- {
- cout << number[i];
- if (number[i+1] != -1)
- cout << '.';
- }
- #ifdef DEBUG1
- cout << " Address: " << hex << this;
- #endif
- cout << endl;
- }
-
- /*------------------------------------------------------------------------
- * Revision::printAll
- *------------------------------------------------------------------------*/
-
- void Revision::printAll (char *indent)
- {
- int i;
- char *nextindent;
-
- cout << indent << "Revision: ";
- printRev ("");
- if (author)
- cout << indent << "Author: " << author << endl;
- if (state)
- cout << indent << "State: " << state << endl;
- if (branches[0])
- {
- cout << indent << "Branches:" << endl;
- nextindent = new char [strlen (indent) + 3];
- strcpy (nextindent, indent);
- strcat (nextindent, " ");
- for (i = 0; (i < MAX_BRANCHES) && branches[i]; i++)
- branches[i]->printRev (nextindent);
- delete [] nextindent;
- }
-
- if (nextRev)
- {
- cout << indent << "Next Revision: ";
- nextRev->printRev ("");
- }
- }
-
- /*========================================================================
- * Symbol class
- *========================================================================*/
-
- class Symbol
- {
- private:
- char *name_string;
- Revision *defined_rev; /* Revision as specified in file */
- Revision *actual_rev; /* Highest revision found so far */
- Symbol *next;
-
- public:
- Symbol (Symbol &s);
- Symbol (char *c = NULL);
- ~Symbol ();
-
- void SetName (char *name);
- void SetDefinedRev (Revision *r);
- int SetActualRev (Revision *r);
-
- void addSymbol (Symbol *s);
- void RecursiveDelete (void) { if (next)
- next->RecursiveDelete ();
- delete next;
- next = NULL; }
-
- char* GetName (void) { return name_string; }
- Revision* getDefinedRev (void) { return defined_rev; }
- Revision* getActualRev (void) { return actual_rev; }
- Symbol* GetNext (void) { return next; }
- void printAll (char *indent);
- };
-
- /*------------------------------------------------------------------------
- * Symbol::Symbol
- *------------------------------------------------------------------------*/
-
- Symbol::Symbol (char *c)
- {
- if (c)
- {
- name_string = new char [sizeof (c) + 1];
- strcpy (name_string, c);
- }
- else
- name_string = NULL;
- defined_rev = NULL;
- actual_rev = NULL;
- next = NULL;
- }
-
- /*------------------------------------------------------------------------
- * Symbol::Symbol
- *------------------------------------------------------------------------*/
-
- Symbol::Symbol (Symbol &s)
- {
- name_string = new char[strlen (s.name_string) + 1];
- strcpy (name_string, s.name_string);
- defined_rev = s.defined_rev;
- actual_rev = s.actual_rev;
- next = s.next;
- }
-
- /*------------------------------------------------------------------------
- * Symbol::~Symbol
- *------------------------------------------------------------------------*/
-
- Symbol::~Symbol ()
- {
- delete [] name_string;
- }
-
- /*------------------------------------------------------------------------
- * Symbol::SetName
- *------------------------------------------------------------------------*/
-
- void Symbol::SetName (char *name)
- {
- name_string = new char [strlen (name) + 1];
- strcpy (name_string, name);
- }
-
- /*------------------------------------------------------------------------
- * Symbol::SetDefinedRev
- *------------------------------------------------------------------------*/
-
- void Symbol::SetDefinedRev (Revision *rev)
- {
- defined_rev = rev;
- }
-
- /*------------------------------------------------------------------------
- * Symbol::SetActualRev
- *------------------------------------------------------------------------*/
-
- int Symbol::SetActualRev (Revision *rev)
- {
- Revision *orig = actual_rev;
- dType returned_type;
-
- if (actual_rev)
- {
- actual_rev = actual_rev->ConditionalSetRevision (rev, defined_rev);
- }
- else
- {
- if (defined_rev)
- {
- returned_type = defined_rev->CompareRevs (*rev);
- if ((returned_type == SAME) || (returned_type == MORE_LEVELS))
- actual_rev = rev;
- }
- else
- actual_rev = rev;
- }
-
- return (orig != actual_rev);
- }
-
- /*------------------------------------------------------------------------
- * Symbol::addSymbol
- *------------------------------------------------------------------------*/
-
- void Symbol::addSymbol (Symbol *s)
- {
- if (next)
- next->addSymbol (s);
- else
- next = s;
- }
-
- /*------------------------------------------------------------------------
- * Symbol::printAll
- *------------------------------------------------------------------------*/
-
- void Symbol::printAll (char *indent)
- {
- char *nextindent;
-
- nextindent = new char [strlen (indent) + 5];
- strcpy (nextindent, indent);
- strcat (nextindent, " ");
-
- if (name_string)
- cout << indent << name_string;
- #ifdef DEBUG1
- cout << " Address: " << hex << this;
- #endif
- cout << endl;
- if (defined_rev)
- {
- cout << indent << "Defined revision:" << endl;
- defined_rev->printRev (nextindent);
- }
- if (actual_rev)
- {
- cout << indent << "Actual revision:" << endl;
- actual_rev->printRev (nextindent);
- }
-
- delete [] nextindent;
- cout << endl;
-
- if (next)
- next->printAll (indent);
- }
-
- /*========================================================================
- * RCSDelta class
- *========================================================================*/
-
- class RCSDelta : public Revision
- {
- private:
- RCSDelta *next;
-
- public:
- RCSDelta (char *c = NULL)
- : Revision (c) { next = NULL; }
- RCSDelta (RCSDelta &r)
- : Revision (r) { next = NULL; }
- /*
- RCSDelta& operator= (Revision &r) { ((Revision *)this) = r;
- next = NULL;
- return *this; }
- */
- void AddDelta (RCSDelta *d);
- RCSDelta *NextDelta (void) { return next; }
- RCSDelta *FindDelta (char *r);
- RCSDelta *FindDelta (Revision &rev);
- RCSDelta *FindBranch (char *r);
- RCSDelta *FindBranch (Revision &rev);
- void RecursiveDelete (void) { if (next)
- next->RecursiveDelete ();
- delete next;
- next = NULL; }
- void printAll (char *indent);
- };
-
- /*------------------------------------------------------------------------
- * RCSDelta::AddDelta
- *------------------------------------------------------------------------*/
-
- void RCSDelta::AddDelta (RCSDelta *d)
- {
- if (next)
- next->AddDelta (d);
- else
- next = d;
- }
-
- /*------------------------------------------------------------------------
- * RCSDelta::FindDelta
- *------------------------------------------------------------------------*/
-
- RCSDelta *RCSDelta::FindDelta (char *r)
- {
- Revision rev (r);
- dType t;
-
- t = CompareRevs (rev);
- if (t == SAME)
- return this;
-
- if (next)
- return next->FindDelta (rev);
-
- return NULL;
- }
-
- /*------------------------------------------------------------------------
- * RCSDelta::FindDelta
- *------------------------------------------------------------------------*/
-
- RCSDelta *RCSDelta::FindDelta (Revision &rev)
- {
- dType t;
-
- t = CompareRevs (rev);
- if (t == SAME)
- return this;
-
- if (next)
- return next->FindDelta (rev);
-
- return NULL;
- }
-
- /*------------------------------------------------------------------------
- * RCSDelta::FindBranch
- *------------------------------------------------------------------------*/
-
- RCSDelta *RCSDelta::FindBranch (char *r)
- {
- Revision rev (r);
- dType t;
-
- t = CompareRevs (rev);
- if ((t == SAME) || (t == MORE_LEVELS))
- return this;
-
- if (next)
- return next->FindDelta (rev);
-
- return NULL;
- }
-
- /*------------------------------------------------------------------------
- * RCSDelta::FindBranch
- *------------------------------------------------------------------------*/
-
- RCSDelta *RCSDelta::FindBranch (Revision &rev)
- {
- dType t;
-
- t = CompareRevs (rev);
- if ((t == SAME) || (t == MORE_LEVELS))
- return this;
-
- if (next)
- return next->FindDelta (rev);
-
- return NULL;
- }
-
- /*------------------------------------------------------------------------
- * RCSDelta::printAll
- *------------------------------------------------------------------------*/
-
- void RCSDelta::printAll (char *indent)
- {
- Revision::printAll (indent);
- cout << endl;
-
- if (next)
- next->printAll (indent);
- }
-
- /*========================================================================
- * Locks class
- *========================================================================*/
-
- class Locks
- {
- private:
- char *user;
- RCSDelta *rev;
- int strict;
- Locks *next;
-
- public:
- Locks ();
- Locks (char *u, RCSDelta *r);
- ~Locks ();
-
- void addLock (Locks *l);
- void RecursiveDelete (void) { if (next)
- next->RecursiveDelete ();
- delete next;
- next = NULL; }
- void setStrict (int state);
- void printAll (char *indent);
- };
-
- /*------------------------------------------------------------------------
- * Locks::Locks
- *------------------------------------------------------------------------*/
-
- Locks::Locks ()
- {
- user = NULL;
- rev = NULL;
- strict = False;
- next = NULL;
- }
-
- /*------------------------------------------------------------------------
- * Locks::Locks
- *------------------------------------------------------------------------*/
-
- Locks::Locks (char *u, RCSDelta *r)
- {
- user = new char [strlen (u) + 1];
- strcpy (user, u);
- rev = r;
- strict = False;
- next = NULL;
- }
-
- /*------------------------------------------------------------------------
- * Locks::~Locks
- *------------------------------------------------------------------------*/
-
- Locks::~Locks ()
- {
- if (user)
- delete [] user;
-
- if (rev)
- delete rev;
- }
-
- /*------------------------------------------------------------------------
- * Locks::addLock
- *------------------------------------------------------------------------*/
-
- void Locks::addLock (Locks *l)
- {
- if (next)
- next->addLock (l);
- else
- next = l;
- }
-
- /*------------------------------------------------------------------------
- * Locks::setStrict
- *------------------------------------------------------------------------*/
-
- void Locks::setStrict (int state)
- {
- strict = state;
- if (next)
- next->setStrict (state);
- }
-
- /*------------------------------------------------------------------------
- * Locks::printAll
- *------------------------------------------------------------------------*/
-
- void Locks::printAll (char *indent)
- {
- if (user)
- cout << indent << "User: " << user;
- #ifdef DEBUG1
- cout << " Address: " << hex << this;
- #endif
- cout << endl;
- cout << indent << "Strict: " << (strict ? "TRUE" : "FALSE") << endl;
- if (rev)
- {
- cout << indent << "Revision: ";
- rev->printRev ("");
- }
- cout << endl;
-
- if (next)
- next->printAll (indent);
- }
-
- /*========================================================================
- * RCSFile class
- *========================================================================*/
-
- class RCSFile
- {
- private:
- char *name;
- Revision *head;
- Revision *branch;
- char *access;
- Symbol *symbols;
- Locks *locks;
- char *comment;
- char *expand;
- RCSDelta *deltas;
-
- public:
- RCSFile (char *file = NULL) { name = file;
- head = NULL;
- branch = NULL;
- access = NULL;
- symbols = NULL;
- locks = NULL;
- comment = NULL;
- expand = NULL;
- deltas = NULL; }
- ~RCSFile ();
- void setHead (char *h);
- void addSymbol (char *sym, char *rev = NULL);
- void addDelta (RCSDelta *r);
- void setBranch (char *b);
- void setAccess (char *c);
- Locks* addLock (char *l);
- void setComment (char *c);
- void setExpand (char *c);
- RCSDelta* FindDelta (char *c);
- void setStrict (int state);
- void printAll (void);
- char* getName (void) { return name; }
- Symbol* getSymbol (void) { return symbols; }
- Revision* getHead (void) { return head; }
- void updateSymbols (RCSDelta *r);
- };
-
- /*------------------------------------------------------------------------
- * RCSFile::~RCSFile
- *------------------------------------------------------------------------*/
-
- RCSFile::~RCSFile ()
- {
- if (access)
- delete access;
- if (symbols)
- {
- symbols->RecursiveDelete ();
- delete symbols;
- }
- if (locks)
- {
- locks->RecursiveDelete ();
- delete locks;
- }
- if (comment)
- delete comment;
- if (deltas)
- {
- deltas->RecursiveDelete ();
- delete deltas;
- }
- }
-
- /*------------------------------------------------------------------------
- * RCSFile::setHead
- *------------------------------------------------------------------------*/
-
- void RCSFile::setHead (char *h)
- {
- RCSDelta *d;
-
- if (head)
- {
- d = deltas->FindDelta (h);
- if (d)
- {
- if (head != d)
- cerr << "RCSFile: Replacing head" << endl;
- }
- else
- {
- d = new RCSDelta (h);
- addDelta (d);
- }
- }
- else
- {
- d = NULL;
- if (deltas)
- d = deltas->FindDelta (h);
-
- if (d == NULL)
- {
- d = new RCSDelta (h);
- addDelta (d);
- }
- }
-
- head = d;
- }
-
- /*------------------------------------------------------------------------
- * RCSFile::addDelta
- *------------------------------------------------------------------------*/
-
- void RCSFile::addDelta (RCSDelta *r)
- {
- if (deltas)
- deltas->AddDelta (r);
- else
- deltas = r;
-
- updateSymbols (r);
- }
-
- /*------------------------------------------------------------------------
- * RCSFile::updateSymbols
- *------------------------------------------------------------------------*/
-
- void RCSFile::updateSymbols (RCSDelta *r)
- {
- Symbol* csymbol;
-
- /*----
- * Scan through the defined symbols and see if there are any
- * that this revision matches.
- *----*/
-
- for (csymbol = symbols; csymbol; csymbol = csymbol->GetNext ())
- {
- csymbol->SetActualRev (r);
- }
- }
-
- /*------------------------------------------------------------------------
- * RCSFile::addSymbol
- *------------------------------------------------------------------------*/
-
- void RCSFile::addSymbol (char *sym, char *rev)
- {
- char *s = sym;
- char *r = rev;
- Symbol *ns;
- RCSDelta *nr = NULL;
-
- if (rev == NULL)
- {
- s = new char [strlen (sym) + 1];
- strcpy (s, sym);
- r = strchr (s, ':');
- if (r)
- *r++ = '\0';
- }
-
- if (r)
- nr = FindDelta (r);
- if (nr == NULL)
- {
- nr = new RCSDelta (r);
- addDelta (nr);
- }
-
- ns = new Symbol (s);
- ns->SetDefinedRev (nr);
- if (symbols)
- symbols->addSymbol (ns);
- else
- symbols = ns;
-
- if (s != sym)
- delete [] s;
- }
-
- /*------------------------------------------------------------------------
- * RCSFile::setBranch
- *------------------------------------------------------------------------*/
-
- void RCSFile::setBranch (char *b)
- {
- RCSDelta *d;
-
- if (branch)
- {
- d = deltas->FindDelta (b);
- if (d)
- {
- if (branch != d)
- cerr << "RCSFile: Replacing branch" << endl;
- }
- else
- {
- d = new RCSDelta (b);
- addDelta (d);
- }
- }
- else
- {
- d = NULL;
- if (deltas)
- d = deltas->FindDelta (b);
-
- if (d == NULL)
- {
- d = new RCSDelta (b);
- addDelta (d);
- }
- }
-
- branch = d;
- }
-
- /*------------------------------------------------------------------------
- * RCSFile::setAccess
- *------------------------------------------------------------------------*/
-
- void RCSFile::setAccess (char *c)
- {
- if (access)
- delete [] access;
-
- access = new char [sizeof (c) + 1];
- strcpy (access, c);
- }
-
- /*------------------------------------------------------------------------
- * RCSFile::addLock
- * l = string containing the following info:
- * <user>:<delta>
- * where:
- * <user> = User name.
- * <delta> = Delta user has checked out.
- *------------------------------------------------------------------------*/
-
- Locks *RCSFile::addLock (char *l)
- {
- char *dstr, *user;
- Locks *lock;
- RCSDelta *d;
-
- dstr = strchr (l, ':');
- if (dstr == NULL)
- {
- dstr = l;
- user = new char [1];
- *user = '\0';
- }
- else
- {
- dstr++;
- user = new char [dstr - l];
- strncpy (user, l, dstr - l - 1);
- user[dstr-l-1] = '\0';
- }
-
- d = NULL;
- if (deltas)
- d = deltas->FindDelta (dstr);
-
- if (d == NULL)
- {
- d = new RCSDelta (dstr);
- deltas->AddDelta (d);
- }
-
- lock = new Locks (user, d);
- if (locks)
- locks->addLock (lock);
- else
- locks = lock;
-
- delete [] user;
- return lock;
- }
-
- /*------------------------------------------------------------------------
- * RCSFile::setComment
- *------------------------------------------------------------------------*/
-
- void RCSFile::setComment (char *c)
- {
- if (comment)
- delete [] comment;
-
- comment = new char [sizeof (c) + 1];
- strcpy (comment, c);
- }
-
- /*------------------------------------------------------------------------
- * RCSFile::setExpand
- *------------------------------------------------------------------------*/
-
- void RCSFile::setExpand (char *c)
- {
- if (expand)
- delete [] expand;
-
- expand = new char [sizeof (c) + 1];
- strcpy (expand, c);
- }
-
- /*------------------------------------------------------------------------
- * RCSFile::FindDelta
- *------------------------------------------------------------------------*/
-
- RCSDelta *RCSFile::FindDelta (char *c)
- {
- if (deltas)
- return deltas->FindDelta (c);
- return NULL;
- }
-
- /*------------------------------------------------------------------------
- * RCSFile::setStrict
- *------------------------------------------------------------------------*/
-
- void RCSFile::setStrict (int state)
- {
- if (locks)
- locks->setStrict (state);
- }
-
- /*------------------------------------------------------------------------
- * RCSFile::printAll
- *------------------------------------------------------------------------*/
-
- void RCSFile::printAll (void)
- {
- cout << "Name: " << name << endl;
- if (head)
- {
- cout << " Head: ";
- head->printRev ("");
- }
- if (branch)
- {
- cout << " Branches:" << endl;
- head->printRev (" ");
- }
- if (access)
- cout << " Access: '" << access << "'" << endl;
- if (symbols)
- {
- cout << " Symbols:" << endl;
- symbols->printAll (" ");
- }
- if (locks)
- {
- cout << " Locks:" << endl;
- locks->printAll (" ");
- }
- if (comment)
- cout << " Comment: '" << comment << "'" << endl;
- if (expand)
- cout << " Expand: " << expand << endl;
- if (deltas)
- {
- cout << " Deltas:" << endl;
- deltas->printAll (" ");
- }
- cout << endl;
- }
-
- /*========================================================================
- * Main subroutines
- *========================================================================*/
-
- static int a_opt = 0, b_opt = 0, t_opt = 0;
- static char *symbol;
- static char *ProgName;
- static char linein[1024], lineout[132];
- static char data_1[1024];
-
- /*------------------------------------------------------------------------
- * readFile
- *------------------------------------------------------------------------*/
-
- RCSFile *readFile (char *filename)
- {
- RCSFile *rcsFile;
- char *cptr, *dptr;
- RCSDelta *aDelta, *bDelta;
- Locks *lock;
-
- /*----
- * Open file and set fptr to the beginning of the root name.
- *----*/
-
- ifstream file (filename);
- if (!file)
- {
- cerr << ProgName << ": Problem opening file " << filename << endl;
- return NULL;
- }
-
- char *fptr = strrchr (filename, '/');
- int line_not_processed, quit;
-
- if (fptr)
- fptr++;
- else
- fptr = filename;
-
- rcsFile = new RCSFile (fptr);
-
- for (quit = 0; !file.eof () && !quit; )
- {
- file.getline (linein, sizeof (linein));
- if (strlen (linein) == 0)
- continue;
-
- cptr = linein;
- for (line_not_processed = 1; line_not_processed; )
- {
- SKIP_SPACE (cptr);
-
- /*----
- * HEAD
- *----*/
-
- if (strncmp (cptr, "head", 4) == 0)
- {
- cptr += 4;
- SKIP_SPACE (cptr);
- for (dptr = data_1; *dptr = *cptr; dptr++, cptr++)
- if (*cptr == ';')
- {
- *dptr = '\0';
- cptr++;
- break;
- }
- rcsFile->setHead (data_1);
- if (*cptr == '\0')
- line_not_processed = 0;
- }
-
- /*----
- * BRANCH
- *----*/
-
- else if (strncmp (cptr, "branch", 6) == 0)
- {
- cptr += 6;
- SKIP_SPACE (cptr);
- for (dptr = data_1; *dptr = *cptr; dptr++, cptr++)
- if (*cptr == ';')
- {
- *dptr = '\0';
- cptr++;
- break;
- }
- rcsFile->setBranch (data_1);
- if (*cptr == '\0')
- line_not_processed = 0;
- }
-
- /*----
- * ACCESS
- *----*/
-
- else if (strncmp (cptr, "access", 6) == 0)
- {
- cptr += 6;
- SKIP_SPACE (cptr);
- for (dptr = data_1; *dptr = *cptr; dptr++, cptr++)
- if (*cptr == ';')
- {
- *dptr = '\0';
- cptr++;
- break;
- }
- rcsFile->setAccess (data_1);
- if (*cptr == '\0')
- line_not_processed = 0;
- }
-
- /*----
- * SYMBOLS
- *----*/
-
- else if (strncmp (cptr, "symbols", 7) == 0)
- {
- cptr += 7;
- SKIP_SPACE (cptr);
- for (dptr = data_1; ((*dptr = *cptr++) != ';'); dptr++)
- {
- if (*dptr == '\0')
- {
- if (dptr != data_1)
- rcsFile->addSymbol (data_1);
- file.getline (linein, sizeof (linein));
- cptr = linein;
- SKIP_SPACE (cptr);
- dptr = data_1 - 1;
- continue;
- }
- if (isspace (*dptr))
- {
- if (dptr != data_1)
- {
- *dptr = '\0';
- rcsFile->addSymbol (data_1);
- dptr = data_1 - 1;
- }
- }
- }
- *dptr = '\0';
- if (dptr != data_1)
- rcsFile->addSymbol (data_1);
- if (*cptr == '\0')
- line_not_processed = 0;
- }
-
- /*----
- * LOCKS
- *----*/
-
- else if (strncmp (cptr, "locks", 5) == 0)
- {
- cptr += 5;
- SKIP_SPACE (cptr);
- for (dptr = data_1; ((*dptr = *cptr++) != ';'); dptr++)
- {
- if (*dptr == '\0')
- {
- if (dptr != data_1)
- lock = rcsFile->addLock (data_1);
- file.getline (linein, sizeof (linein));
- cptr = linein;
- SKIP_SPACE (cptr);
- dptr = data_1 - 1;
- continue;
- }
- if (isspace (*dptr))
- {
- if (dptr != data_1)
- {
- *dptr = '\0';
- lock = rcsFile->addLock (data_1);
- dptr = data_1 - 1;
- }
- }
- }
- *dptr = '\0';
- if (dptr != data_1)
- lock = rcsFile->addLock (data_1);
-
- if (*cptr != '\0')
- {
- SKIP_SPACE (cptr);
- if (strncmp (cptr, "strict", 6) == 0)
- {
- cptr += 6;
- rcsFile->setStrict (True);
- while (*cptr++ != ';');
- }
- }
- if (*cptr == '\0')
- line_not_processed = 0;
- }
-
- /*----
- * COMMENT
- *----*/
-
- else if (strncmp (cptr, "comment", 7) == 0)
- {
- cptr += 7;
- while (*cptr && (*cptr++ != '@'));
-
- for (dptr = data_1; 1; dptr++, cptr++)
- {
- while (*cptr == '\0')
- {
- if (file.eof ())
- {
- *dptr = '\0';
- break;
- }
- file.getline (linein, sizeof (linein));
- cptr = linein;
- *dptr++ = '\n';
- }
- if ((*dptr = *cptr) == '\0')
- break;
- if (*cptr == '@')
- {
- *dptr = '\0';
- break;
- }
- }
- while (*cptr && (*cptr++ != ';'));
-
- rcsFile->setComment (data_1);
- if (*cptr == '\0')
- line_not_processed = 0;
- }
-
- /*----
- * EXPAND
- *----*/
-
- else if (strncmp (cptr, "expand", 6) == 0)
- {
- cptr += 6;
- while (*cptr && (*cptr++ != '@'));
-
- for (dptr = data_1; 1; dptr++, cptr++)
- {
- while (*cptr = '\0')
- {
- if (file.eof ())
- {
- *dptr = '\0';
- break;
- }
- file.getline (linein, sizeof (linein));
- cptr = linein;
- *dptr++ = '\n';
- }
- if ((*dptr = *cptr) == '\0')
- break;
- if (*cptr == '@')
- {
- *dptr = '\0';
- break;
- }
- if (*cptr == ';')
- {
- *dptr = '\0';
- break;
- }
- }
- while (*cptr && (*cptr++ != ';'));
-
- rcsFile->setExpand (data_1);
- if (*cptr == '\0')
- line_not_processed = 0;
- }
-
- /*----
- * DESC
- *----*/
-
- else if (strncmp (cptr, "desc", 4) == 0)
- {
- cptr += 4;
- quit = 1;
- break;
- }
-
- /*----
- * Should be a revision
- *----*/
-
- else if (isdigit (*cptr))
- {
- for (dptr = cptr; *cptr && (*cptr != ';'); cptr++);
- *cptr = '\0';
-
- aDelta = rcsFile->FindDelta (dptr);
- if (aDelta == NULL)
- {
- aDelta = new RCSDelta (dptr);
- rcsFile->addDelta (aDelta);
- }
- rcsFile->updateSymbols (aDelta);
-
- while (!file.eof ())
- {
- file.getline (linein, sizeof (linein));
- if (strlen (linein) == 0)
- break;
-
- cptr = linein;
- for (line_not_processed = 1; line_not_processed; )
- {
- SKIP_SPACE (cptr);
-
- /*----
- * DATE
- *----*/
-
- if (strncmp (cptr, "date", 4) == 0)
- {
- cptr += 4;
- SKIP_SPACE (cptr);
- for (dptr = cptr; *cptr && (*cptr != ';');
- cptr++);
- *cptr++ = '\0';
- if (*cptr == '\0')
- line_not_processed = 0;
- }
-
- /*----
- * AUTHOR
- *----*/
-
- else if (strncmp (cptr, "author", 6) == 0)
- {
- cptr += 6;
- SKIP_SPACE (cptr);
- for (dptr = cptr; *cptr && (*cptr != ';');
- cptr++);
- *cptr++ = '\0';
- aDelta->SetAuthor (dptr);
- if (*cptr == '\0')
- line_not_processed = 0;
- }
-
- /*----
- * STATE
- *----*/
-
- else if (strncmp (cptr, "state", 5) == 0)
- {
- cptr += 5;
- SKIP_SPACE (cptr);
- for (dptr = cptr; *cptr && (*cptr != ';');
- cptr++);
- *cptr++ = '\0';
- aDelta->SetState (dptr);
- if (*cptr == '\0')
- line_not_processed = 0;
- }
-
- /*----
- * BRANCHES
- *----*/
-
- else if (strncmp (cptr, "branches", 8) == 0)
- {
- cptr += 8;
- SKIP_SPACE (cptr);
- for (dptr = data_1;
- ((*dptr = *cptr++) != ';');
- dptr++)
- {
- if (*dptr == '\0')
- {
- if (dptr != data_1)
- {
- bDelta =
- rcsFile->FindDelta (data_1);
- if (bDelta == NULL)
- {
- bDelta = new RCSDelta (data_1);
- rcsFile->addDelta (bDelta);
- }
- // bDelta->AddBranch (bDelta);
- }
- file.getline (linein, sizeof (linein));
- cptr = linein;
- SKIP_SPACE (cptr);
- dptr = data_1 - 1;
- }
- if (isspace (*dptr))
- {
- if (dptr != data_1)
- {
- *dptr = '\0';
- bDelta =
- rcsFile->FindDelta (data_1);
- if (bDelta == NULL)
- {
- bDelta = new RCSDelta (data_1);
- rcsFile->addDelta (bDelta);
- }
- // bDelta->AddBranch (bDelta);
- }
- }
- }
- *dptr = '\0';
- if (dptr != data_1)
- {
- bDelta = rcsFile->FindDelta (data_1);
- if (bDelta == NULL)
- {
- bDelta = new RCSDelta (data_1);
- rcsFile->addDelta (bDelta);
- }
- // bDelta->AddBranch (bDelta);
- }
- if (*cptr == '\0')
- line_not_processed = 0;
- }
-
- /*----
- * NEXT
- *----*/
-
- else if (strncmp (cptr, "next", 4) == 0)
- {
- cptr += 4;
- SKIP_SPACE (cptr);
- for (dptr = data_1; *dptr = *cptr++; dptr++)
- if (*dptr == ';')
- {
- *dptr = '\0';
- break;
- }
- if (strlen (data_1) > 0)
- {
- bDelta = rcsFile->FindDelta (data_1);
- if (bDelta == NULL)
- {
- bDelta = new RCSDelta (data_1);
- rcsFile->addDelta (bDelta);
- }
- aDelta->SetNext (bDelta);
- }
- if (*cptr == '\0')
- line_not_processed = 0;
- }
- }
- }
- }
- }
- }
- file.close();
-
- return rcsFile;
- }
-
- /*========================================================================
- * MAIN ROUTINE
- *========================================================================*/
-
- main (int argc, char *argv[])
- {
- extern char *optarg;
- extern int optind, opterr, optopt;
- int c;
- int errflg = 0;
- struct stat statbuf;
- char **fileptr;
- RCSFile *rcsFile;
- char *cptr;
- Symbol *csymbol;
- Revision *rev;
-
- symbol = NULL;
-
- /*----
- * Figure out the program name without path.
- *----*/
-
- ProgName = strrchr (argv[0], '/');
- if (ProgName)
- ProgName++;
- else
- ProgName = argv[0];
-
- /*----
- * Collect options from command line.
- *----*/
-
- while ((c = getopt (argc, argv, "abts:")) != EOF)
- {
- switch (c) {
- case 'a':
- a_opt = 1;
- break;
-
- case 'b':
- b_opt = 1;
- break;
-
- case 't':
- t_opt = 1;
- break;
-
- case 's':
- symbol = optarg;
- break;
-
- case '?':
- errflg++;
- }
- }
-
- /*----
- * If an error occurred, print usage.
- *----*/
-
- if (errflg || optind >= argc)
- {
- cerr << "Usage: " << ProgName
- << " [-bl] [[-a] -s <symbol>] { <file-list> | <directory> }"
- << endl;
- cerr << " -a Print all files even if symbol not defined"
- << endl;
- cerr << " -b Print base revision number for each symbol"
- << endl;
- cerr << " -t Do not print title lines" << endl;
- return 0;
- }
-
- /*----
- * Find out if the first entry is a file or a directory.
- *----*/
-
- if (stat (argv[optind], &statbuf) != 0)
- {
- cerr << ProgName << ": Unable to get stat of " << argv[optind] << endl;
- cerr << strerror (errno) << endl;
- return 1;
- }
-
- if (S_ISDIR (statbuf.st_mode))
- {
- cerr << ProgName << ": Directories not yet supported." << endl;
- return -1;
- }
- else
- {
- fileptr = &argv[optind];
- }
-
- if (t_opt == 0)
- {
- cout << "File\t\t\tSymbol\t";
- if (b_opt)
- cout << "Base\t";
- cout << "Revision\tState" << endl;
- cout << "----\t\t\t------\t";
- if (b_opt)
- cout << "----\t";
- cout << "--------\t-----" << endl;
- }
-
- /*----
- * Now start looping through the files/directory.
- *----*/
-
- for ( ; *fileptr; fileptr++)
- {
- if (stat (*fileptr, &statbuf) != 0)
- {
- cerr << ProgName << ": Unable to get stat of " << *fileptr
- << endl;
- cerr << strerror (errno) << endl;
- continue;
- }
-
- if (S_ISDIR (statbuf.st_mode))
- continue;
-
- rcsFile = readFile (*fileptr);
- if (rcsFile == NULL)
- continue;
-
- #ifdef DEBUG
- rcsFile->printAll ();
- #endif
-
- cptr = rcsFile->getName ();
- c = strlen (cptr);
- strcpy (lineout, cptr);
-
- csymbol = rcsFile->getSymbol ();
-
- if (symbol == NULL)
- {
- cout << lineout;
- lineout[0] = '\0';
-
- rev = rcsFile->getHead ();
- if (rev)
- {
- TAB_OUT (c, 24);
- cout << "<Head>";
-
- TAB_OUT (c, 32+(8*b_opt));
- cptr = rev->GetRevision ();
- cout << cptr;
- c += strlen (cptr);
-
- TAB_OUT (c, 48+(8*b_opt));
- cptr = rev->GetState ();
- cout << cptr;
-
- cout << endl;
- c = 0;
- }
- }
-
- if (csymbol)
- {
- for ( ; csymbol; csymbol = csymbol->GetNext ())
- {
- if (symbol)
- if (strcmp (symbol, csymbol->GetName ()) != 0)
- continue;
-
- if (lineout[0])
- {
- cout << lineout;
- lineout[0] = '\0';
- }
-
- TAB_OUT (c, 24)
- cptr = csymbol->GetName ();
- cout << cptr;
- c += strlen (cptr);
-
- if (b_opt)
- {
- rev = csymbol->getDefinedRev ();
- if (rev)
- {
- TAB_OUT (c, 32);
- cptr = rev->GetRevision ();
- cout << cptr;
- c += strlen (cptr);
- }
- }
-
- rev = csymbol->getActualRev ();
- if (rev)
- {
- TAB_OUT (c, 32+(8*b_opt));
- cptr = rev->GetRevision ();
- cout << cptr;
- c += strlen (cptr);
-
- TAB_OUT (c, 48+(8*b_opt));
- cptr = rev->GetState ();
- cout << cptr;
- }
- cout << endl;
- c = 0;
- }
- }
-
- if (lineout[0] && a_opt)
- {
- cout << lineout;
- TAB_OUT (c, 24);
- cout << symbol;
- TAB_OUT (c, 32);
- cout << "<Undefined>" << endl;
- }
-
- delete rcsFile;
- }
- }
-